package com.pactera.madp.cp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.common.core.constant.SecurityConstants;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.cp.api.dto.emp.EmployeeCreateDoDTO;
import com.pactera.madp.cp.api.dto.emp.EmployeeCreateDoNewDTO;
import com.pactera.madp.cp.api.dto.emp.EmployeeDoCreateDTO;
import com.pactera.madp.cp.api.dto.emp.EmployeeDoUpdateDTO;
import com.pactera.madp.cp.api.em.workcontact.EventEnum;
import com.pactera.madp.cp.api.entity.*;
import com.pactera.madp.cp.api.entity.employeeWechat.EmployeeDoEntity;
import com.pactera.madp.cp.api.entity.employeeWechat.EmployeeFollowEntity;
import com.pactera.madp.cp.api.feign.RemoteEmployeeDoService;
import com.pactera.madp.cp.api.page.SubPage;
import com.pactera.madp.cp.api.vo.employee.EmployeeDoVO;
import com.pactera.madp.cp.api.vo.employee.EmployeeInfoWechatVO;
import com.pactera.madp.cp.common.util.PageUtil;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.ContactEmployeeTrackMapper;
import com.pactera.madp.cp.mapper.EmployeeDoMapper;
import com.pactera.madp.cp.service.*;
import lombok.Data;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (CpEmployeeDo)表服务实现类
 *
 * @author yushen.qi
 * @since 2021-06-29 15:08:13
 */
@Service
@Data
public class EmployeeDoServiceImpl extends ServiceImpl<EmployeeDoMapper, EmployeeDoEntity> implements EmployeeDoService {

    private final IWorkContactService iWorkContactService;
    private final IWorkEmployeeService iWorkEmployeeService;
    @Resource
    private ContactEmployeeTrackMapper contactEmployeeTrackMapper;
    @Resource
    private RemoteEmployeeDoService remoteEmployeeDoService;
    @Resource
    private IContactService contactService;
    @Resource
    private EmployeeFollowService employeeFollowService;
    @Resource
    private ContactEmployeeTrackService contactEmployeeTrackService;
    private final IWorkContactEmployeeService workContactEmployeeService;

    @Override
    public R<Boolean> insert(EmployeeCreateDoDTO dto) {
        ZoneId zoneId2 = ZoneId.systemDefault();
        ZonedDateTime zdt = dto.getStartTime().atZone(zoneId2);
        Date date = Date.from(zdt.toInstant());
        if (date.before(new Date())) {
            throw new IllegalArgumentException("提醒时间应在当前时间之后");
        }
        Integer corpId = CorpContextHolder.getCorpId();
        WorkContactEntity contactEntity = iWorkContactService.getOne(
                Wrappers.<WorkContactEntity>lambdaQuery()
                        .eq(WorkContactEntity::getWxExternalUserid, dto.getWxExternalUserid())
                        .eq(WorkContactEntity::getCorpId, corpId)
                        .eq(BaseEntity::getDelFlag, 0)
        );
        EmployeeDoEntity employeeDoEntity = new EmployeeDoEntity();
        BeanUtil.copyProperties(dto,employeeDoEntity);
        employeeDoEntity.setUpdateTime(LocalDateTime.now());
        employeeDoEntity.setCreateTime(LocalDateTime.now());
        employeeDoEntity.setDoState(2);
        employeeDoEntity.setCorpId(corpId);
        employeeDoEntity.setAvatar(contactEntity.getAvatar());
        employeeDoEntity.setName(contactEntity.getName());
        employeeDoEntity.setNickName(contactEntity.getNickName());
        employeeDoEntity.setStartTime(date);
        employeeDoEntity.setWxUserId(dto.getWxUserId());
        employeeDoEntity.setWxExternalUserid(dto.getWxExternalUserid());
        boolean save = save(employeeDoEntity);
        if (save) {
            EmployeeDoEntity one = getOne(
                    Wrappers.<EmployeeDoEntity>lambdaQuery()
                            .orderByDesc(EmployeeDoEntity::getId)
                            .last("limit 1")
            );
            EmployeeDoCreateDTO employeeDoCreateDTO = new EmployeeDoCreateDTO();
            EmployeeCreateDoNewDTO newDTO = new EmployeeCreateDoNewDTO();
            newDTO.setWxExternalUserid(dto.getWxExternalUserid());
            newDTO.setWxUserId(dto.getWxUserId());
            newDTO.setContent(dto.getDoBody());
            newDTO.setCorpId(corpId);
            newDTO.setTodoId(one.getId());
            String s = JSON.toJSONString(newDTO);
            employeeDoCreateDTO.setMethodParamsValue(s);
            employeeDoCreateDTO.setCreateBy(dto.getWxUserId());
            employeeDoCreateDTO.setCreateTime(dto.getStartTime());
            employeeDoCreateDTO.setCronExpression(conversion(dto.getStartTime()));
            employeeDoCreateDTO.setMethodName("sendTodo");
            employeeDoCreateDTO.setJobTenantType("1");
            employeeDoCreateDTO.setJobType("2");
            employeeDoCreateDTO.setJobName("sendTodo" + one.getId());
            employeeDoCreateDTO.setJobGroup("behaviorTrackTask");
            employeeDoCreateDTO.setClassName("behaviorTrackTask");
            employeeDoCreateDTO.setRemark("待办事项任务");
            employeeDoCreateDTO.setMisfirePolicy("3");
            return remoteEmployeeDoService.save(employeeDoCreateDTO, SecurityConstants.FROM_IN);
        } else {
            return R.failed("新增失败");
        }
    }

    @Override
    public boolean update(EmployeeDoUpdateDTO dto) {
        ZoneId zoneId2 = ZoneId.systemDefault();
        ZonedDateTime zdt = dto.getStartTime().atZone(zoneId2);
        Date date = Date.from(zdt.toInstant());
        if (date.before(new Date())) {
            throw new IllegalArgumentException("提醒时间应在当前时间之后");
        }
        EmployeeDoEntity employeeDoEntity = new EmployeeDoEntity();
        employeeDoEntity.setId(dto.getId());
        employeeDoEntity.setDoBody(dto.getDoBody());
        employeeDoEntity.setStartTime(date);
        return update(employeeDoEntity, Wrappers.<EmployeeDoEntity>lambdaQuery().eq(EmployeeDoEntity::getId, dto.getId()));
    }

    @Override
    public void state(Integer id, Integer state) {
        EmployeeDoEntity employeeDoEntity = new EmployeeDoEntity();
        employeeDoEntity.setId(id);
        employeeDoEntity.setDoState(state);
        update(employeeDoEntity, Wrappers.<EmployeeDoEntity>lambdaQuery().eq(EmployeeDoEntity::getId, id));
    }

    @Override
    public IPage listByState(Page page, Integer state, String wxExternalUserid, String wxUserId) {
        Integer corpId = CorpContextHolder.getCorpId();
        LambdaQueryWrapper<EmployeeDoEntity> wrapper = Wrappers.lambdaQuery();
        if(state != null) {
            wrapper.eq(StrUtil.isNotBlank(wxUserId),EmployeeDoEntity::getWxUserId, wxUserId)
                    .eq(StrUtil.isNotBlank(wxExternalUserid),EmployeeDoEntity::getWxExternalUserid, wxExternalUserid)
                    .eq(EmployeeDoEntity::getDoState, state)
                    .eq(EmployeeDoEntity::getDelFlag, 0)
                    .eq(EmployeeDoEntity::getCorpId, corpId)
                    .orderByAsc(EmployeeDoEntity::getStartTime);
            IPage iPage = baseMapper.selectPage(page, wrapper);
            List collect = (List) iPage.getRecords().stream().map(entity -> {
                EmployeeDoVO employeeDoVO = new EmployeeDoVO();
                BeanUtil.copyProperties(entity, employeeDoVO);
                return employeeDoVO;
            }).collect(Collectors.toList());
            iPage.setRecords(collect);
            return iPage;
        } else {
            //按照开始时间正序排,并且进行中的代办排前面，结束的代办排后面
            wrapper.eq(StrUtil.isNotBlank(wxUserId),EmployeeDoEntity::getWxUserId, wxUserId)
                    .eq(StrUtil.isNotBlank(wxExternalUserid),EmployeeDoEntity::getWxExternalUserid, wxExternalUserid)
                    .eq(EmployeeDoEntity::getDelFlag, 0)
                    .eq(EmployeeDoEntity::getCorpId, corpId)
                    .orderByAsc(EmployeeDoEntity::getStartTime);
            List<EmployeeDoEntity> employeeDoEntities = baseMapper.selectList(wrapper);
            ArrayList<EmployeeDoVO> resultList = new ArrayList<>();
            ArrayList<EmployeeDoVO> collect1 = (ArrayList<EmployeeDoVO>) employeeDoEntities.stream()
                    .filter(entity -> entity.getDoState().equals(2))
                    .sorted(Comparator.comparing(entity -> entity.getStartTime()))
                    .map(entity -> {
                        EmployeeDoVO employeeDoVO = new EmployeeDoVO();
                        BeanUtil.copyProperties(entity, employeeDoVO);
                        return employeeDoVO;
                    }).collect(Collectors.toList());
            resultList.addAll(collect1);

            ArrayList<EmployeeDoVO> collect2 = (ArrayList<EmployeeDoVO>) employeeDoEntities.stream()
                    .filter(entity -> entity.getDoState().equals(1))
                    .sorted(Comparator.comparing(entity -> entity.getStartTime()))
                    .map(entity -> {
                        EmployeeDoVO employeeDoVO = new EmployeeDoVO();
                        BeanUtil.copyProperties(entity, employeeDoVO);
                        return employeeDoVO;
                    }).collect(Collectors.toList());
            resultList.addAll(collect2);

            Page<EmployeeDoVO> resultPage = PageUtil.split(resultList, (int) page.getCurrent(), (int) page.getSize());
            return resultPage;
        }


    }

    @Override
    public List<EmployeeDoVO> listByStateList(String wxUserId) {
        return list(Wrappers.<EmployeeDoEntity>lambdaQuery()
                .eq(EmployeeDoEntity::getWxUserId,wxUserId)
                .eq(EmployeeDoEntity::getDoState,2)
                .orderByAsc(EmployeeDoEntity::getStartTime).last("limit 2"))
                .stream().map(employeeDoEntity -> {
                    EmployeeDoVO vo = new EmployeeDoVO();
                    BeanUtil.copyProperties(employeeDoEntity,vo);

                    WorkEmployeeEntity workEmployeeEntity = iWorkEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                            .eq(WorkEmployeeEntity::getCorpId, employeeDoEntity.getCorpId())
                            .eq(WorkEmployeeEntity::getWxUserId, employeeDoEntity.getWxUserId()));

                    WorkContactEntity contactEntity = iWorkContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery()
                            .eq(WorkContactEntity::getCorpId, employeeDoEntity.getCorpId())
                            .eq(WorkContactEntity::getWxExternalUserid, employeeDoEntity.getWxExternalUserid()));

                    if (ObjectUtil.isNotNull(workEmployeeEntity) && ObjectUtil.isNotNull(contactEntity)){
                        WorkContactEmployeeEntity employeeEntity = workContactEmployeeService.getOne(Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                                .eq(WorkContactEmployeeEntity::getEmployeeId, workEmployeeEntity.getId())
                                .eq(WorkContactEmployeeEntity::getContactId, contactEntity.getId())
                                .eq(WorkContactEmployeeEntity::getCorpId, employeeDoEntity.getCorpId()));

                        if (ObjectUtil.isNotNull(employeeEntity)){
                            vo.setNickName(employeeEntity.getRemark());
                            vo.setRemark(employeeEntity.getRemark());
                        }
                    }

                    return vo;
                }).collect(Collectors.toList());
    }

    public Page<List<EmployeeDoVO>> getInfoDoPage(String wxUserId, Page page) {
        Integer corpId = CorpContextHolder.getCorpId();
        List<EmployeeDoVO> vos = baseMapper.getInfoDoPage(corpId, wxUserId, page);
        Page<EmployeeDoVO> split = PageUtil.split(vos, (int) page.getCurrent(), (int) page.getSize());
        SubPage subPage = new SubPage();
        subPage.setRecords(split.getRecords());
        subPage.setCurrent(split.getCurrent());
        subPage.setSize(split.getSize());
        subPage.setTotal(split.getTotal());
        return subPage;
    }

    public Page<EmployeeInfoWechatVO> getInfoFollowPage(String wxUserId,Page page){
        Integer corpId = CorpContextHolder.getCorpId();
        LocalDateTime now = LocalDateTime.now();
        page = (Page) employeeFollowService.page(page, Wrappers.<EmployeeFollowEntity>lambdaQuery()
                .eq(EmployeeFollowEntity::getWxUserId, wxUserId)
                .eq(EmployeeFollowEntity::getCorpId, corpId)
                .orderByDesc(EmployeeFollowEntity::getCreateTime));

        List<EmployeeFollowEntity> list = page.getRecords();

        List<EmployeeInfoWechatVO> follows = list.stream().map(entity -> {
                    EmployeeInfoWechatVO follow = new EmployeeInfoWechatVO();
                    follow.setId(entity.getId());
                    follow.setContent(entity.getFollowBody());
                    follow.setTime(DateUtil.format(DateUtil.date(entity.getCreateTime()),"yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime createTime = entity.getCreateTime();
                    Duration duration = Duration.between(createTime, now);
                    if (duration.toMinutes() < 15) {
                        follow.setState(2);
                    } else {
                        follow.setState(1);
                    }
                    return follow;
                }).collect(Collectors.toList());

        page.setRecords(follows);
        return page;
    }

    public Page<EmployeeInfoWechatVO> getInfoInteractionPage(String wxUserId, Page page) {
        Integer corpId = CorpContextHolder.getCorpId();
        LocalDateTime now = LocalDateTime.now();
        WorkEmployeeEntity workEmployeeInfo = iWorkEmployeeService.getWorkEmployeeInfo(wxUserId);
        if (Objects.isNull(workEmployeeInfo)) {
            throw new CheckedException("该员工不存在");
        }
        page = (Page) contactEmployeeTrackService.page(page, Wrappers.<ContactEmployeeTrackEntity>lambdaQuery()
                .eq(ContactEmployeeTrackEntity::getEmployeeId, workEmployeeInfo.getId())
                .eq(ContactEmployeeTrackEntity::getCorpId, corpId)
                .orderByDesc(ContactEmployeeTrackEntity::getCreateTime));
        List<ContactEmployeeTrackEntity> list = page.getRecords();

        List<EmployeeInfoWechatVO> interactions = list.stream().map(entity -> {
                    EmployeeInfoWechatVO interaction = new EmployeeInfoWechatVO();
                    interaction.setId(entity.getId());
                    interaction.setContent(entity.getContent());
                    interaction.setTime(DateUtil.format(DateUtil.date(entity.getCreateTime()), "yyyy-MM-dd HH:mm:ss"));
                    interaction.setTitle(EventEnum.getByCode(entity.getEvent()));
                    LocalDateTime createTime = entity.getCreateTime();
                    Duration duration = Duration.between(createTime, now);
                    if (duration.toMinutes() < 15) {
                        interaction.setState(2);
                    } else {
                        interaction.setState(1);
                    }
                    return interaction;
                }).collect(Collectors.toList());
        page.setRecords(interactions);
        return page;
    }
//    @Override
//    public EmployeeInfoWechatVO getInfoList(String wxUserId) {
//        Integer corpId = CorpContextHolder.getCorpId();
//        LocalDateTime now = LocalDateTime.now();
//        EmployeeInfoWechatVO employeeInfoWechatVO = new EmployeeInfoWechatVO();
//        List<EmployeeInfoWechatVO.Do> doList = getDo(wxUserId, corpId, now);
//        employeeInfoWechatVO.setDoList(doList);
//        List<EmployeeInfoWechatVO.Follow> follows = getFollow(wxUserId, corpId, now);
//        employeeInfoWechatVO.setFollowList(follows);
//        List<EmployeeInfoWechatVO.Interaction> interaction = getInteraction(wxUserId, corpId, now);
//        employeeInfoWechatVO.setInteractionList(interaction);
//        return employeeInfoWechatVO;
//    }

    /**
     * 时间点转换成corn表达式
     * 如：2019-04-28 00:30:30，表示定时任务会在2019-04-28 00:30:30执行
     * @param date 执行日期
     * @return String
     */
    public static String conversion(LocalDateTime date) {
        StringBuilder str = new StringBuilder();
        Calendar calendar = Calendar.getInstance();
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = date.atZone(zone).toInstant();
        Date from = Date.from(instant);
        calendar.setTime(from);
        str.append(calendar.get(Calendar.SECOND))
                .append(" ")
                .append(calendar.get(Calendar.MINUTE))
                .append(" ")
                .append(calendar.get(Calendar.HOUR_OF_DAY))
                .append(" ")
                .append(calendar.get(Calendar.DAY_OF_MONTH))
                .append(" ")
                .append(calendar.get(Calendar.MONTH) + 1)
                .append(" ")
                .append("?")
                .append(" ")
                .append(calendar.get(Calendar.YEAR))
                .append("-")
                .append(calendar.get(Calendar.YEAR));
        return str.toString();
    }

}
